View Javadoc

1   package org.apache.maven.surefire.junitcore;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.concurrent.atomic.AtomicBoolean;
26  import java.util.concurrent.atomic.AtomicInteger;
27  import org.apache.maven.surefire.report.ConsoleOutputReceiver;
28  import org.apache.maven.surefire.report.ReportEntry;
29  import org.apache.maven.surefire.report.RunListener;
30  import org.apache.maven.surefire.report.SimpleReportEntry;
31  
32  import org.junit.runner.Description;
33  
34  /**
35   * * Represents the test-state of a testset that is run.
36   */
37  public class TestSet
38  {
39      private final Description testSetDescription;
40  
41      private final AtomicInteger numberOfCompletedChildren = new AtomicInteger( 0 );
42  
43      // While the two parameters below may seem duplicated, it is not entirely the case,
44      // since numberOfTests has the correct value from the start, while testMethods grows as method execution starts.
45  
46      private final AtomicInteger numberOfTests = new AtomicInteger( 0 );
47  
48      private final List<TestMethod> testMethods = Collections.synchronizedList( new ArrayList<TestMethod>() );
49  
50      private static final InheritableThreadLocal<TestSet> testSet = new InheritableThreadLocal<TestSet>();
51  
52      private final AtomicBoolean allScheduled = new AtomicBoolean();
53  
54      private final AtomicBoolean played = new AtomicBoolean();
55  
56      private volatile LogicalStream beforeClass;
57  
58      private volatile LogicalStream afterClass;
59  
60      public TestSet( Description testSetDescription )
61      {
62          this.testSetDescription = testSetDescription;
63      }
64  
65      public void replay( RunListener target )
66      {
67          if ( !played.compareAndSet( false, true ) )
68          {
69              return;
70          }
71  
72          try
73          {
74              ReportEntry report = createReportEntry( null );
75  
76              target.testSetStarting( report );
77  
78              if ( beforeClass != null )
79              {
80                  beforeClass.writeDetails( ( (ConsoleOutputReceiver) target ) );
81              }
82  
83              int elapsed = 0;
84              for ( TestMethod testMethod : testMethods )
85              {
86                  elapsed += testMethod.getElapsed();
87                  testMethod.replay( target );
88              }
89  
90              report = createReportEntry( elapsed );
91  
92              if ( afterClass != null )
93              {
94                  afterClass.writeDetails( ( (ConsoleOutputReceiver) target ) );
95              }
96              target.testSetCompleted( report );
97          }
98          catch ( Exception e )
99          {
100             throw new RuntimeException( e );
101         }
102     }
103 
104     public TestMethod createThreadAttachedTestMethod( ReportEntry description )
105     {
106         TestMethod testMethod = new TestMethod( description, this );
107         addTestMethod( testMethod );
108         testMethod.attachToThread();
109         return testMethod;
110     }
111 
112     private ReportEntry createReportEntry( Integer elapsed )
113     {
114         boolean isJunit3 = testSetDescription.getTestClass() == null;
115         String classNameToUse =
116             isJunit3 ? testSetDescription.getChildren().get( 0 ).getClassName() : testSetDescription.getClassName();
117         return new SimpleReportEntry( classNameToUse, classNameToUse, elapsed );
118     }
119 
120     public void incrementTestMethodCount()
121     {
122         numberOfTests.incrementAndGet();
123     }
124 
125     private void addTestMethod( TestMethod testMethod )
126     {
127         testMethods.add( testMethod );
128     }
129 
130     public void incrementFinishedTests( RunListener reporterManager, boolean reportImmediately )
131     {
132         numberOfCompletedChildren.incrementAndGet();
133         if ( allScheduled.get() && isAllTestsDone() && reportImmediately )
134         {
135             replay( reporterManager );
136         }
137     }
138 
139     public void setAllScheduled( RunListener reporterManager )
140     {
141         allScheduled.set( true );
142         if ( isAllTestsDone() )
143         {
144             replay( reporterManager );
145         }
146     }
147 
148     private boolean isAllTestsDone()
149     {
150         return numberOfTests.get() == numberOfCompletedChildren.get();
151     }
152 
153     public void attachToThread()
154     {
155         testSet.set( this );
156     }
157 
158     public static TestSet getThreadTestSet()
159     {
160         return testSet.get();
161     }
162 
163     public LogicalStream getClassLevelLogicalStream()
164     {
165         if ( numberOfCompletedChildren.get() > 0 )
166         {
167             if ( afterClass == null )
168             {
169                 afterClass = new LogicalStream();
170             }
171             return afterClass;
172         }
173         else
174         {
175             if ( beforeClass == null )
176             {
177                 beforeClass = new LogicalStream();
178             }
179             return beforeClass;
180         }
181     }
182 
183 
184 }